package com.jewaton.auth.commons.service.impl;

import com.jewaton.auth.commons.entity.Role;
import com.jewaton.auth.commons.service.AbstractRBACService;
import com.jewaton.auth.commons.service.RBACService;
import com.jewaton.auth.commons.util.Pager;
import com.jewaton.auth.commons.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import java.util.*;

@Service("accountRBACService")
public class AccountRBACServiceImpl extends AbstractRBACService implements
        RBACService {
    
    private static final Log log = LogFactory.getLog(AccountRBACServiceImpl.class);

    @Override
    public void assginAccountRole(String originRoleIds, String changeRoleIds, long aid) {
        String[] origin = originRoleIds.split("#");
        String[] change = changeRoleIds.split("#");
        String[] toAddArray = StringUtil.getMinus(change, origin);
        String[] toDelArray = {};
        String toAdd = StringUtil.getArrayString(toAddArray);
        int countAdd = toAddArray.length;
        String toDel = "";
        int countDel = 0;
        
        if(!StringUtil.isBlank(originRoleIds)) {
            toDelArray = StringUtil.getMinus(origin, change);
            countDel = toDelArray.length;
            toDel = StringUtil.getArrayString(toDelArray);
        }       
        
        if (countDel > 0) {
            if (deleteAccountRoles(aid, toDel) != countDel) {
//                throw new RuntimeException("要删除的角色:" + toDel + "跟实际删除的角色列表不符");
            	log.info("要删除的角色:" + toDel + "跟实际删除的角色列表不符");
            }
        }

        if (countAdd > 0) {
            if (addAccountRoles(aid, toAdd) != countAdd) {
//                throw new RuntimeException("要增加的角色:" + toDel + "跟实际增加的角色列表不符");
                log.info("要增加的角色:" + toDel + "跟实际增加的角色列表不符");
            }
        }
    }
    

    @Override
    public List<Map<String, Object>> getAssginRoleByOrgId(long aid, String oid) {
        List<Role> roleList = getRoleDAO().getAssginRoleByOrgId(oid);
        List<Object> list = getRoleDAO().getRoleOfAccount(aid);
        List<Map<String,Object>> assginList = new ArrayList<Map<String,Object>>();
        for (Role r : roleList) {
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("rid", r.getRid());
            map.put("roleName", r.getRoleName());
            map.put("description", r.getDescription());
            map.put("type", r.getType());
            map.put("createTime", r.getCreateTime());
            for (Object obj : list) {
                long roleAccountId = Long.valueOf(obj.toString());
                if (r.getRid() == roleAccountId)  {
                    map.put("checked", true);
                }
            }
            assginList.add(map);
        }
        return assginList;
    }

    @Override
    public Pager<Role> getAllPcRole(int pageNo, int pageSize,String roleName, String oid) {
        return getRoleDAO().getAllPcRole(pageNo, pageSize, roleName, oid);
    }

    @Override
    public List<Map<String, Object>> getPcPermissionTree(boolean showCode) {
        List<Map<String, Object>> treeList = getPermissionDAO().getPcPermMenuList(showCode); 
        treeList.addAll(getPermissionDAO().getPcPermOauthList(showCode));  
        return treeList;
    }

    @Override
    public List<Map<String, Object>> getPcPermissionTreeOfOrg(String oid,
            boolean showAll, boolean setChecked, boolean showCode) {
        List<Object[]> checkList = getPermissionDAO().getPermOfOrg(oid);
        List<Map<String, Object>> treeList = getPcPermissionTree(showCode); 
        if (checkList.size() > 0) {
            for (Map<String,Object> map : treeList) {
                long pid = Long.valueOf(map.get("value").toString());
                for (Object[] obj : checkList) {
                    long checkPid = Long.valueOf(obj[0].toString());
                    if (pid == checkPid) {
                        map.put("checked", true);
                    }
                }
            }
        }
        if (!showAll) {
            Iterator<Map<String, Object>> i = treeList.iterator();
            while (i.hasNext()) {
                Map<String, Object> map =  i.next();
                boolean isChecked =  map.get("checked") == null ? false : true;
                if (!isChecked) {
                    i.remove();
                } else {
                    if (!setChecked) 
                        map.remove("checked");
                }
            }
        }
        return treeList;    
    }

    @Override
    public List<Map<String, Object>> getPcPermissionTreeOfRole(String oid,
            long rid, boolean showAll, boolean showCode) {
        List<Map<String, Object>> treeList = getPcPermissionTreeOfOrg(oid, false, false, showCode); 
        List<Object[]> checkList = getPermissionDAO().getPermOfRole(rid);
        if(checkList.size() > 0) {
            for (Map<String,Object> map : treeList) {
                long pid = Long.valueOf(map.get("value").toString());
                for (Object[] obj : checkList) {
                    long checkPid = Long.valueOf(obj[0].toString());
                    if (pid == checkPid) {
                        map.put("checked", true);
                    }
                }
            }
        }   
        if (!showAll) {
            Iterator<Map<String, Object>> i = treeList.iterator();
            while (i.hasNext()) {
                Map<String, Object> map =  i.next();
                boolean isChecked =  map.get("checked") == null ? false : true;
                if (!isChecked) {
                    i.remove();
                }
            }
        }       
        return treeList;    
    }

    @Override
    public List<Map<String, Object>> viewPcPermissionTreeOfOrg(String oid, boolean showCode) {
        return getPcPermissionTreeOfOrg(oid, false, true, showCode);
    }

    @Override
    public List<Map<String, Object>> viewPcPermissionTreeOfRole(String oid,
            long rid, boolean showCode) {
        return getPcPermissionTreeOfRole(oid, rid, false, showCode);
    }

    @Override
    public void updatePcOrgPermissions(String oid, String originPermissions,
            String changePermissions) {
        String[] origin = originPermissions.split("#");
        String[] change = changePermissions.split("#");
        String[] toAddArray = StringUtil.getMinus(change, origin);
        String[] toDelArray = {};
        String toAdd = StringUtil.getArrayString(toAddArray);
        int countAdd = toAddArray.length;
        String toDel = "";
        int countDel = 0;
        
        if(!StringUtil.isBlank(originPermissions)) {
            toDelArray = StringUtil.getMinus(origin, change);
            countDel = toDelArray.length;
            toDel = StringUtil.getArrayString(toDelArray);
        }
        
        int maxInCount = 1000;
        
        if (countDel > 0) {
            if (countDel > maxInCount) {
                log.info("组织编码： " + oid + " 要删除的权限id集合个数:" + countDel + " 大于1000个 分批删除");
                int ratio = countDel / maxInCount;
                int mod = countDel % maxInCount;
                log.debug("countDel:" + countDel + " ratio: " + ratio + " mod:" + mod);
                for (int i=0; i<ratio; i++) {
                    String[] subToDelArray = new String[maxInCount];
                    System.arraycopy(toDelArray, i * maxInCount, subToDelArray, 0, maxInCount);
                    deleteOrgPermissions(oid, StringUtil.getArrayString(subToDelArray));
                }
                if (mod > 0) {
                    String[] subToDelArray = new String[mod];
                    System.arraycopy(toDelArray, countDel - mod, subToDelArray, 0, mod);
                    deleteOrgPermissions(oid, StringUtil.getArrayString(subToDelArray));
                }
            } else {
                if (deleteOrgPermissions(oid, toDel) != countDel ) {
    //                throw new RuntimeException("组织编码： " + oid + " 要删除的权限id集合:" + toDel + "跟实际删除的权限列表不符");
                	log.info("组织编码： " + oid + " 要删除的权限id集合:" + toDel + "跟实际删除的权限列表不符");
                }
            }
        }
        if (countAdd > 0) {
            if (countAdd > maxInCount) {
                log.info("组织编码： " + oid + " 要增加的权限id集合个数:" + countAdd + " 大于1000个 分批增加");
                int ratio = countAdd / maxInCount;
                int mod = countAdd % maxInCount;
                log.debug("countAdd:" + countAdd + " ratio: " + ratio + " mod:" + mod);
                for (int i=0; i<ratio; i++) {
                    String[] subToAddArray = new String[maxInCount];
                    System.arraycopy(toAddArray, i * maxInCount, subToAddArray, 0, maxInCount);
                    addOrgPermissions(oid, StringUtil.getArrayString(subToAddArray));
                }
                if (mod > 0) {
                    String[] subToAddArray = new String[mod];
                    System.arraycopy(toAddArray, countAdd - mod, subToAddArray, 0, mod);
                    addOrgPermissions(oid, StringUtil.getArrayString(subToAddArray));
                }
            } else {
                if (addOrgPermissions(oid, toAdd) != countAdd ) {
    //                throw new RuntimeException("组织编码： " + oid + " 要增加的权限id集合:" + toAdd + "跟实际添加的权限列表不符");
                    log.info("组织编码： " + oid + " 要增加的权限id集合:" + toAdd + "跟实际添加的权限列表不符");
                }
            }
        }        
    }

    private int addOrgPermissions(String oid, String permissionValues) {
        permissionValues = StringUtil.getSQLInValues(permissionValues);
        return getPermissionDAO().addOrgPermissions(oid, permissionValues);
    }
    private int deleteOrgPermissions(String oid, String permissionValues) {
        permissionValues = StringUtil.getSQLInValues(permissionValues);
        return getPermissionDAO().deleteOrgPermissions(oid, permissionValues);
    }
    private int addAccountRoles(long aid, String roleIds) {
        roleIds = StringUtil.getSQLInValues(roleIds);
        return getRoleDAO().addAccountRole(aid, roleIds);
    }
    private int deleteAccountRoles(long aid, String roleIds) {
        roleIds = StringUtil.getSQLInValues(roleIds);
        return getRoleDAO().deleteAccountRole(aid, roleIds);
    }
    
}
